package com.common.shiro;

import com.pojo.Admin;
import com.pojo.Menu;
import com.pojo.ShiroAdmin;
import com.server.AdminService;
import com.server.MenuService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @description shiro 登录授权认证
 */
public class PersonRealm extends AuthorizingRealm {

    @Resource
    AdminService adminService;

    @Resource
    MenuService menuService;

    /**
     * 登录的验证实现方法
     * Shiro登录认证(原理：用户提交 用户名和密码  ---shiro 封装令牌---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制 )
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken AdminInfoToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken) AdminInfoToken;
        //通过登录名查找账户及其对应的角色id
        Admin admin=adminService.findAdminByLoginName(token.getUsername());
        if(admin == null) {
            throw new UnknownAccountException("用户名或密码有误！");
        }
        // 将数据放到 ShiroAdmin(VO) 中。后面将信息存进shiro中
        ShiroAdmin shiroAdmin=new ShiroAdmin(admin.getAdminid(), admin.getName(), admin.getPassword(), admin.getRolemid());
        //加盐
        ByteSource salt=ByteSource.Util.bytes(admin.getName());
        /**
         * 最后一步交给 shiro
         * 认证缓存信息
         *
         * principals: 可以使用户名，或d登录用户的对象
         * hashedCredentials: 从数据库中获取的密码
         * credentialsSalt：密码加密的盐值
         * RealmName:  类名（ShiroRealm）
         */
        SimpleAuthenticationInfo getInfo=new SimpleAuthenticationInfo(shiroAdmin, admin.getPassword(), salt,getName());
        //框架完成验证
        return getInfo;
    }

    /**
     * Shiro权限认证
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //  从principals得到用户身份信息
        ShiroAdmin shiroAdmin=(ShiroAdmin) principals.getPrimaryPrincipal();
        //  得到用户角色 id
        int roleId =shiroAdmin.shiroRoleId;
        List<String> urlarrayList = new ArrayList<>() ;

        List<Menu> menuList = menuService.getAllMenus(roleId);
        for (Menu menu:menuList) {
            if (menu.getUrl()!=null){
                urlarrayList.add(menu.getUrl());
            }
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(urlarrayList);//这里添加用户的访问权限列表
        return info;
    }

    //清除当前用户权限信息
    public void clearCached() {
        //获取当前等的用户凭证，然后清除
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }
}
